<template>
  <div>

    <!-- 切割控制区域 -->
    <div class="cut-controls">
      <label>切割高度: </label>
      <input type="number" v-model.number="cutValue" @change="updateCutPlane" />

      <div class="buttons">
        <button @click="setCut(26, 'overall')">整体</button>
        <button @click="setCut(12, 'floor4M')">4M层</button>
        <button @click="setCut(7, 'floor4')">4层</button>
        <button @click="setCut(2, 'floor3M')">3M层</button>
        <button @click="setCut(-1.6, 'floor3')">3层</button>
        <button @click="setCut(-8, 'floor2M')">2M层</button>
        <button @click="setCut(-13, 'floor2')">2层</button>
        <button @click="setCut(-19, 'floor1M')">1M层</button>
        <button @click="setCut(-22, 'floor1')">1层</button>
        <button @click="logCamera">打印相机参数</button>
      </div>

      <div style="margin-top:10px;">
        <label>Marker角度(°): </label>
        <input type="number" v-model.number="markerRotation" @change="updateMarkerRotation" />
      </div>

      <!-- 新增：摄像头 FOV 控制 -->
      <div style="margin-top:10px;">
        <label>视野角度(°): </label>
        <input type="number" v-model.number="markerFOVAngle" @change="updateMarkerFOV" /><br>
        <label> 半径: </label>
        <input type="number" v-model.number="markerFOVRadius" @change="updateMarkerFOV" />
      </div>
    </div>
    <div ref="threeContainer" class="three-container"></div>


    <!-- 右键菜单 -->
    <div v-if="menuVisible" :style="{ top: menuY + 'px', left: menuX + 'px' }" class="marker-menu">
      <div @click="editMarker">编辑</div>
      <div @click="deleteMarker">删除</div>
    </div>
  </div>
</template>

<script>
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import gsap from "gsap";

export default {
  data() {
    return {
      scene: null,
      camera: null,
      renderer: null,
      model: null,
      controls: null,
      topPlane: null,
      cutValue: 26,
      raycaster: null,
      mouse: null,

      // 多 marker 管理
      markers: [],
      draggingMarker: null,
      draggingHandle: null,
      selectedMarker: null,

      markerRotation: 30,

      // 摄像头 FOV 默认值
      markerFOVAngle: 60,
      markerFOVRadius: 20,

      // 右键菜单
      menuVisible: false,
      menuX: 0,
      menuY: 0,

      cameraPresets: {
        overall: { x: 30.59, y: 10.97, z: 98.74, target: { x: 5.40, y: -13.58, z: 0.58 } },
        floor4M: { x: 49.93, y: 62.82, z: 57.46, target: { x: 8.81, y: -17.86, z: 3.49 } },
        floor4: { x: 41.16, y: 34.48, z: 84.16, target: { x: 6.51, y: -16.64, z: 4.14 } },
        floor3M: { x: 38.99, y: 47.98, z: 59.49, target: { x: 10.55, y: -14.91, z: 14.02 } },
        floor3: { x: 2.23, y: 71.01, z: 30.69, target: { x: 1.26, y: -3.60, z: 10.13 } },
        floor2M: { x: 21.69, y: -7.58, z: 85.81, target: { x: 1.93, y: -17.14, z: 2.37 } },
        floor2: { x: 21.69, y: -7.58, z: 85.81, target: { x: 1.93, y: -17.14, z: 2.37 } },
        floor1M: { x: 21.69, y: -7.58, z: 85.81, target: { x: 1.93, y: -17.14, z: 2.37 } },
        floor1: { x: 21.69, y: -7.58, z: 85.81, target: { x: 1.93, y: -17.14, z: 2.37 } }
      }
    };
  },
  methods: {
    logCamera() {
      console.log("📷 Camera pos:", this.camera.position);
      console.log("🎯 Target:", this.controls.target);
    },

    initThree() {
      this.scene = new THREE.Scene();
      this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
      this.camera.position.set(30.59, 10.97, 98.74);

      const ambientLight = new THREE.AmbientLight(0xffffff, 2.6);
      this.scene.add(ambientLight);
      const directionalLight = new THREE.DirectionalLight(0xffffff, 2.8);
      directionalLight.position.set(10, 20, 10);
      this.scene.add(directionalLight);

      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.setClearColor(0x000c29);
      this.renderer.localClippingEnabled = true;
      this.$refs.threeContainer.appendChild(this.renderer.domElement);

      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.target.set(5.40, -13.58, 0.58);
      this.controls.update();

      this.topPlane = new THREE.Plane(new THREE.Vector3(0, -1, 0), this.cutValue);
      this.raycaster = new THREE.Raycaster();
      this.mouse = new THREE.Vector2();

      this.loadModel();
      this.animate();
      window.addEventListener("resize", this.onResize);

      // 右键菜单事件
      this.renderer.domElement.addEventListener("contextmenu", this.onRightClick);
      window.addEventListener("click", this.hideMarkerMenu);
    },

    cloneMatWithClipping(mat) {
      if (!mat) return mat;
      if (Array.isArray(mat)) {
        return mat.map((m) => {
          const nm = m.clone ? m.clone() : m;
          nm.clippingPlanes = [this.topPlane];
          return nm;
        });
      } else {
        const nm = mat.clone ? mat.clone() : mat;
        nm.clippingPlanes = [this.topPlane];
        return nm;
      }
    },

    loadModel() {
      const loader = new GLTFLoader();
      loader.load(
        "7.glb",
        (gltf) => {
          this.model = gltf.scene;
          this.model.traverse((child) => {
            if (child.isMesh) {
              const oldMat = child.material;
              if (Array.isArray(oldMat)) {
                child.material = oldMat.map((m) => new THREE.MeshBasicMaterial({
                  map: m.map || null,
                  color: m.color || 0xffffff,
                  transparent: m.transparent || false,
                  opacity: m.opacity !== undefined ? m.opacity : 1,
                  alphaMap: m.alphaMap || null,
                  side: m.side || THREE.FrontSide,
                  clippingPlanes: [this.topPlane]
                }));
              } else {
                child.material = new THREE.MeshBasicMaterial({
                  map: oldMat.map || null,
                  color: oldMat.color || 0xffffff,
                  transparent: oldMat.transparent || false,
                  opacity: oldMat.opacity !== undefined ? oldMat.opacity : 1,
                  alphaMap: oldMat.alphaMap || null,
                  side: oldMat.side || THREE.FrontSide,
                  clippingPlanes: [this.topPlane]
                });
              }
            }
          });
          this.scene.add(this.model);
        },
        undefined,
        (error) => { console.error("模型加载失败：", error); }
      );
    },

    updateCutPlane() {
      this.topPlane.constant = this.cutValue;
    },

    setCut(val, presetName) {
      gsap.to(this.topPlane, { constant: val, duration: 1, ease: "power2.out" });
      const preset = this.cameraPresets[presetName];
      if (preset) {
        gsap.to(this.camera.position, { x: preset.x, y: preset.y, z: preset.z, duration: 1.2, ease: "power2.inOut" });
        gsap.to(this.controls.target, { x: preset.target.x, y: preset.target.y, z: preset.target.z, duration: 1.2, ease: "power2.inOut", onUpdate: () => this.controls.update() });
      }
    },

    createMarker(textureUrl, position) {
      const pivot = new THREE.Object3D();
      pivot.position.copy(position);
      this.scene.add(pivot);

      const map = new THREE.TextureLoader().load(textureUrl);
      const geometry = new THREE.PlaneGeometry(3.6, 1.9);
      const material = new THREE.MeshBasicMaterial({ map, transparent: true });
      const marker = new THREE.Mesh(geometry, material);
      marker.rotation.x = -Math.PI / 2;
      pivot.add(marker);

      const sphereGeo = new THREE.SphereGeometry(0.5, 16, 16);
      const sphereMat = new THREE.MeshBasicMaterial({ color: 0xffffff });
      const rotationHandle = new THREE.Mesh(sphereGeo, sphereMat);
      rotationHandle.position.set(3, 1, 0);
      pivot.add(rotationHandle);

      this.markers.push({ pivot, marker, rotationHandle });
      this.selectedMarker = this.markers[this.markers.length - 1];
    },

    getPlaneIntersection(event) {
      const rect = this.renderer.domElement.getBoundingClientRect();
      this.mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
      this.mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
      this.raycaster.setFromCamera(this.mouse, this.camera);
      const intersection = new THREE.Vector3();
      if (this.raycaster.ray.intersectPlane(this.topPlane, intersection)) return intersection;
      return null;
    },

    onCanvasClick(event) {
      const pos = this.getPlaneIntersection(event);
      if (!pos) return;
      this.createMarker("sx7.png", pos);
    },

    onPointerDown(event) {
      const rect = this.renderer.domElement.getBoundingClientRect();
      this.mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
      this.mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
      this.raycaster.setFromCamera(this.mouse, this.camera);

      for (const m of this.markers) {
        if (this.raycaster.intersectObject(m.rotationHandle, true).length > 0) {
          this.draggingHandle = m;
          this.selectedMarker = m;
          this.controls.enabled = false;
          return;
        }
        if (this.raycaster.intersectObject(m.marker, true).length > 0) {
          this.draggingMarker = m;
          this.selectedMarker = m;
          this.controls.enabled = false;
          return;
        }
      }
    },

    onPointerMove(event) {
      const pos = this.getPlaneIntersection(event);
      if (!pos) return;

      if (this.draggingMarker) this.draggingMarker.pivot.position.copy(pos);
      if (this.draggingHandle) {
        const dx = pos.x - this.draggingHandle.pivot.position.x;
        const dz = pos.z - this.draggingHandle.pivot.position.z;
        this.draggingHandle.pivot.rotation.y = Math.atan2(dx, dz);
      }
    },

    onPointerUp() {
      if (this.draggingMarker || this.draggingHandle) {
        this.draggingMarker = null;
        this.draggingHandle = null;
        this.controls.enabled = true;
      }
    },

    updateMarkerRotation() {
      if (this.selectedMarker) {
        this.selectedMarker.pivot.rotation.y = THREE.MathUtils.degToRad(this.markerRotation);
      }
    },

    // 右键菜单逻辑
    onRightClick(event) {
      event.preventDefault();
      const rect = this.renderer.domElement.getBoundingClientRect();
      this.mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
      this.mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
      this.raycaster.setFromCamera(this.mouse, this.camera);

      for (const m of this.markers) {
        if (this.raycaster.intersectObject(m.marker, true).length > 0) {
          this.selectedMarker = m;
          this.showMarkerMenu(event.clientX, event.clientY);
          return;
        }
      }
    },

    showMarkerMenu(x, y) {
      this.menuX = x;
      this.menuY = y;
      this.menuVisible = true;
    },

    hideMarkerMenu() {
      this.menuVisible = false;
    },

    deleteMarker() {
      if (!this.selectedMarker) return;
      const index = this.markers.indexOf(this.selectedMarker);
      if (index !== -1) {
        this.scene.remove(this.selectedMarker.pivot);
        this.markers.splice(index, 1);
      }
      this.hideMarkerMenu();
      this.selectedMarker = null;
    },

    editMarker() {
      if (!this.selectedMarker) return;
      alert("这里可以放编辑逻辑，比如修改贴图或旋转");
      this.hideMarkerMenu();
    },

    animate() {
      requestAnimationFrame(this.animate);
      this.controls.update();
      this.renderer.render(this.scene, this.camera);
    },

    onResize() {
      const w = window.innerWidth;
      const h = window.innerHeight;
      this.camera.aspect = w / h;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(w, h);
    },

    // === 创建扇形几何体 ===
    createCameraFOVMesh(radius = 20, angle = 60) {
      const rad = THREE.MathUtils.degToRad(angle);
      const geometry = new THREE.CircleGeometry(radius, 64, -rad / 2, rad);
      const material = new THREE.MeshBasicMaterial({
        color: 0x00ff00,
        transparent: true,
        opacity: 0.25,
        side: THREE.DoubleSide,
        depthWrite: false
      });
      const fovMesh = new THREE.Mesh(geometry, material);
      fovMesh.rotation.x = -Math.PI / 2;
      fovMesh.position.y = 0.01;
      return fovMesh;
    },

    createMarker(textureUrl, position) {
      const pivot = new THREE.Object3D();
      pivot.position.copy(position);
      this.scene.add(pivot);

      // 摄像头图标
      const map = new THREE.TextureLoader().load(textureUrl);
      const geometry = new THREE.PlaneGeometry(3.6, 1.9);
      const material = new THREE.MeshBasicMaterial({ map, transparent: true });
      const marker = new THREE.Mesh(geometry, material);
      marker.rotation.x = -Math.PI / 2;
      pivot.add(marker);

      // === 添加摄像头视野扇形 ===
      const fov = this.createCameraFOVMesh(this.markerFOVRadius, this.markerFOVAngle);
      pivot.add(fov);

      // 旋转手柄
      const sphereGeo = new THREE.SphereGeometry(0.5, 16, 16);
      const sphereMat = new THREE.MeshBasicMaterial({ color: 0xffffff });
      const rotationHandle = new THREE.Mesh(sphereGeo, sphereMat);
      rotationHandle.position.set(3, 1, 0);
      pivot.add(rotationHandle);

      this.markers.push({ pivot, marker, rotationHandle, fov });
      this.selectedMarker = this.markers[this.markers.length - 1];
    },

    updateMarkerRotation() {
      if (this.selectedMarker) {
        this.selectedMarker.pivot.rotation.y = THREE.MathUtils.degToRad(this.markerRotation);
      }
    },

    // === 动态更新 FOV ===
    updateMarkerFOV() {
      if (!this.selectedMarker) return;
      const { fov, pivot } = this.selectedMarker;
      pivot.remove(fov); // 移除旧扇形
      const newFov = this.createCameraFOVMesh(this.markerFOVRadius, this.markerFOVAngle);
      pivot.add(newFov);
      this.selectedMarker.fov = newFov;
    },
  },

  mounted() {
    this.initThree();
    this.renderer.domElement.addEventListener("dblclick", this.onCanvasClick);
    this.renderer.domElement.addEventListener("pointerdown", this.onPointerDown);
    this.renderer.domElement.addEventListener("pointermove", this.onPointerMove);
    this.renderer.domElement.addEventListener("pointerup", this.onPointerUp);
  },

  beforeDestroy() {
    window.removeEventListener("resize", this.onResize);
    this.renderer.domElement.removeEventListener("dblclick", this.onCanvasClick);
    this.renderer.domElement.removeEventListener("pointerdown", this.onPointerDown);
    this.renderer.domElement.removeEventListener("pointermove", this.onPointerMove);
    this.renderer.domElement.removeEventListener("pointerup", this.onPointerUp);
    this.renderer.domElement.removeEventListener("contextmenu", this.onRightClick);
    window.removeEventListener("click", this.hideMarkerMenu);
  }
};
</script>

<style scoped>
.three-container {
  width: 100%;
  height: 100%;
  /* position: absolute;
  left: 0;
  top: 0; */
  background-color: #212830;
  overflow: hidden;
}

.cut-controls {
  width: 250px;
  height: 250px;
  position: absolute;
  top: 200px;
  left: 20px;
  /* color: white; */
  z-index: 10;
  background: rgba(0, 0, 0, 0.4);
  padding: 10px;
  border-radius: 8px;
}

.cut-controls input {
  width: 100px;
  margin-left: 10px;
}

.buttons{
  display: flex;
  justify-content: flex-start;
  align-items: center;
  flex-wrap: wrap;
}

label{
  color: white;
}

.buttons button {
  background: #0073ff;
  border: none;
  color: white;
  padding: 6px 10px;
  border-radius: 6px;
  cursor: pointer;
  margin-left: 10px;
  margin-top: 10px;
}

.buttons button:hover {
  background: #3399ff;
}

.marker-menu {
  position: absolute;
  background: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 6px 10px;
  border-radius: 6px;
  z-index: 20;
  cursor: pointer;
}

.marker-menu div:hover {
  background: #333;
}
</style>
